package com.xuexi.mianshi;

import java.util.Scanner;

/**
 * 旋转的数字
 */

public class RotatingDigit {

    /**
     * 全局思想是从内到外开始旋转
     * 首先：确定数字1的开始位置
     * 1x1  1(0,0)
     * 2x2  1(0,0)
     * <p>
     * 3x3  1(1,1)
     * 4x4  1(1,1)
     * <p>
     * 5x5  1(2,2)
     * 6x6  1(2,2)
     * <p>
     * 7x7  1(3,3)
     * 8x8  1(3,3)
     * <p>
     * 可以看到一个规律，矩阵的平方根等于奇数时1的坐标点位置是 1（平方根 / 2，平方根 / 2）
     * 矩阵的平方根等于奇数时1的坐标点位置是 1（平方根 / 2 - 1，平方根 / 2 - 1）
     *
     * @param args
     */

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入一个目标数: ");
        int num = scanner.nextInt();

        double sqrt = Math.sqrt(num);
        //对平方根向上取整得到理想的方阵
        int pfg = (int) Math.ceil(sqrt);
        int[][] fz = new int[pfg][pfg];
        //得到开始点 1 的下标位置
        int index = pfg % 2 == 0 ? pfg / 2 - 1 : pfg / 2;
        //1的起始位置
        fz[index][index] = 1;
        //旋转的自增数字，自增到目标数字num，起始位置已经有了，所以从2开始
        int numincr = 2;
        //下左上右旋转,从2的位置开始
        boolean down = true, left = false, up = false, right = false;
        //初始化一个横向和纵向的初始坐标
        int hx = Integer.MIN_VALUE;
        int zx = Integer.MIN_VALUE;
        //定义一个最小的平方根递增到理想的平方根
        for (int minPfg = 2; minPfg <= pfg; minPfg++) {
            //这里假设一下上一个左边点的位置
            if (zx == Integer.MIN_VALUE && hx == Integer.MIN_VALUE) {
                //假设数字2上面的数字的坐标点
                hx = index - 1;
                zx = index + 1;
            }
            //移动的步长
            int stepSize = 2 * minPfg - 1;
            int tmp = stepSize;
            //把平方根每增加1需要每增加数字个数看做循环的次数,2n-1
            for (int times = 2 * minPfg - 1; times > 0; times--) {
                if (numincr <= num) {
                    if (down) {
                        //向下走 横向坐标+1
                        hx++;
                        fz[hx][zx] = numincr;
                        numincr++;
                        //步长-1
                        tmp--;
                        if (stepSize - tmp == minPfg) {
                            down = false;
                            left = true;
                        }
                    } else if (left) {
                        //向左走 纵向坐标-1
                        zx--;
                        fz[hx][zx] = numincr;
                        numincr++;
                        //步长-1
                        tmp--;
                        if (tmp == 0) {
                            left = false;
                            up = true;
                            //开始旋转，假设上一个坐标点的位置，为下一个数建立参考点
                            hx++;
                            zx--;
                        }
                    } else if (up) {
                        //向上走 横向坐标-1
                        hx--;
                        fz[hx][zx] = numincr;
                        numincr++;
                        //步长-1
                        tmp--;
                        if (stepSize - tmp == minPfg) {
                            up = false;
                            right = true;
                        }
                    } else if (right) {
                        //向右走 总向坐标+1
                        zx++;
                        fz[hx][zx] = numincr;
                        numincr++;
                        //步长-1
                        tmp--;
                        if (tmp == 0) {
                            right = false;
                            down = true;
                            //开始旋转，假设上一个坐标点的位置，为下一个数建立参考点
                            hx--;
                            zx++;
                        }
                    }
                }
            }
        }
        for (int[] ints : fz) {
            for (int i = 0; i < ints.length; i++) {
                System.out.print(ints[i] == 0 ? "\t" : ints[i] + "\t");
            }
            System.out.println();
        }
        scanner.close();
    }
}
